﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Windows;
using black_screen_mode_server;

namespace black_screen_mode_server
{
    class Monitor
    {
        /// <summary>
        /// 连接主从服务器    
        /// </summary>
        static string connectionString = "server=LAPTOP-CKCFDD72;Database=TestDatabase;User Id=sa;Password=bageling;";  //本地
        static string[] remoteConnectionStrings;
        static SqlConnection primaryConnection;
        static SqlConnection secondaryConnection;
        private static bool isPrimaryConnection = true;       
        public static void InitializeConnections()
        {
            using (SqlConnection localConnection = new SqlConnection(connectionString))
            {
                localConnection.Open();
                SqlCommand command = new SqlCommand("SELECT server_name, hostname FROM server_info", localConnection);
                SqlDataReader reader = command.ExecuteReader();
                remoteConnectionStrings = reader.Cast<DbDataRecord>().Select(r => $"Data Source={r["server_name"]};Initial Catalog={r["database_name"]};Integrated Security=True;").ToArray();
            }
        }
        public static void RemoteConnectToDatabases()
        {
            if (remoteConnectionStrings == null || remoteConnectionStrings.Length < 2)
            {
                MessageBox.Show("远程连接字符串未正确初始化!");
            }
            
            try
            {
                if (isPrimaryConnection)
                {
                    primaryConnection = new SqlConnection(remoteConnectionStrings[0]);
                    primaryConnection.Open();
                }
                else
                {
                    secondaryConnection = new SqlConnection(remoteConnectionStrings[1]);
                    secondaryConnection.Open();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("连接远程服务器失败!" + ex.Message);
            }
        }
        public static void RestorePrimaryConnection()
        {
            if (!isPrimaryConnection)
            {
                secondaryConnection.Close();
                primaryConnection = new SqlConnection(remoteConnectionStrings[0]);
                primaryConnection.Open();

                isPrimaryConnection = true;

                Console.WriteLine("Primary connection restored.");
            }
        }


        public Monitor()
        {
            InitializeConnections();
            RemoteConnectToDatabases();
            RestorePrimaryConnection();
            Dictionary<string, int> groupParameters = LoadGroupParameters();
            int frequency = LoadFrequency();

            while (true)
            {
                List<string> groups = GetDistinctGroupsFromWhiteList();

                foreach (string group in groups)
                {
                    int delayTime = groupParameters[group];
                    ProcessGroup(group, delayTime, frequency);
                }
                Thread.Sleep(frequency);
            }
        }

        static Dictionary<string, int> LoadGroupParameters()
        {
            Dictionary<string, int> groupParameters = new Dictionary<string, int>();

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();

                string query = "SELECT point_group, delay_time FROM parameters_info";

                using (SqlCommand command = new SqlCommand(query, connection))
                {
                    SqlDataReader reader = command.ExecuteReader();
                    int groupIndex = reader.GetOrdinal("piont_group");
                    int delayTimeIndex = reader.GetOrdinal("delay_time");

                    while (reader.Read())
                    {
                        string group = reader.GetString(groupIndex);
                        int delayTime = reader.GetInt32(delayTimeIndex);
                        groupParameters[group] = delayTime;
                    }
                    reader.Close();
                }
            }
            return groupParameters;
        }

        static int LoadFrequency()
        {
            int frequency = 0;

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();

                string query = "SELECT frequency FROM parameters_info";

                using (SqlCommand command = new SqlCommand(query, connection))
                {
                    frequency = (int)command.ExecuteScalar();
                }
            }

            return frequency;
        }

        static List<string> GetDistinctGroupsFromWhiteList()
        {
            List<string> groups = new List<string>();

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();

                string query = "SELECT DISTINCT category FROM white_list";

                using (SqlCommand command = new SqlCommand(query, connection))
                {
                    SqlDataReader reader = command.ExecuteReader();

                    while (reader.Read())
                    {
                        string group = reader.GetString(0);
                        groups.Add(group);
                    }

                    reader.Close();
                }
            }

            return groups;
        }

        static void ProcessGroup(string group, int delayTime, int frequency)
        {
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();

                while (delayTime > 0)
                {
                    bool hasNewData = CheckIfNewDataExists(group, connection);

                    if (hasNewData)
                    {
                        string latestCategory = GetLatestCategory(group, connection);

                        if (latestCategory == "1")
                        {
                            delayTime = ResetCountdownTimer(group, connection);
                            RecordToDatabase(group, connection, "Process Alarm");
                            break;
                        }
                        else if (latestCategory == "3")
                        {
                            delayTime = ResetCountdownTimer(group, connection);
                            RecordToDatabase(group, connection, "System Alarm");
                            break;
                        }
                        else if (latestCategory == "7")
                        {
                            delayTime = ResetCountdownTimer(group, connection);
                            RecordToDatabase(group, connection, "Operator Change");
                            break;
                        }
                    }

                    delayTime--;
                    Thread.Sleep(1000);
                }

                StartTimer(group, delayTime, frequency);  
            }
        }

        static bool CheckIfNewDataExists(string group, SqlConnection connection)
        {
            string query = @"SELECT COUNT(*) FROM event
                         WHERE tag IN (
                             SELECT tag FROM all_points
                             WHERE tag NOT IN (
                                 SELECT tag FROM white_list WHERE category = @Group))"; 

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Group", group);
                int count = Convert.ToInt32(command.ExecuteScalar());
                return count > 0;
            }
        }

        static string GetLatestCategory(string group, SqlConnection connection)
        {
            string query = @"SELECT TOP 1 category FROM event
                         WHERE tag IN (
                             SELECT tag FROM all_points
                             WHERE tag NOT IN (
                                 SELECT tag FROM white_list WHERE category = @Group))
                         ORDER BY create_date DESC";

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Group", group);
                string category = (string)command.ExecuteScalar();
                return category;
            }
        }

        static int ResetCountdownTimer(string group, SqlConnection connection)
        {
            int countdownTimer = 0;

            while (true)
            {
                bool hasNewData = CheckIfNewDataExists(group, connection);

                if (hasNewData)
                {
                    
                    string latestCategory = GetLatestCategory(group, connection);

                    if (latestCategory == "1")
                    {
                        countdownTimer = GetCountdownTimeForGroup(group, connection);
                        RecordToDatabase(group, connection, "Process Alarm");
                        break;
                    }
                    else if (latestCategory == "3")
                    {
                        countdownTimer = GetCountdownTimeForGroup(group, connection);
                        RecordToDatabase(group, connection, "System Alarm");
                        break;
                    }
                    if (latestCategory == "7")
                    {
                        countdownTimer = GetCountdownTimeForGroup(group, connection);
                        RecordToDatabase(group, connection, "Operator Change");
                        break;
                    }
                }

                Thread.Sleep(1000);
            }

            return countdownTimer;
        }

        static int GetCountdownTimeForGroup(string group, SqlConnection connection)
        {
            
            string query = "SELECT delay_time FROM parameters_info WHERE point_group = @Group";

            using (SqlCommand command = new SqlCommand(query, connection))
            {
                command.Parameters.AddWithValue("@Group", group);
                int countdownTime = (int)command.ExecuteScalar();
                return countdownTime;
            }
        }

        static void RecordToDatabase(string group, SqlConnection connection, string alarmType) //记录数据（）
        {
            using (SqlCommand command = connection.CreateCommand())
            {
                command.CommandText = "INSERT INTO report (group, alarm_type, start_time) VALUES (@Group, @AlarmType, GETDATE())";
                command.Parameters.AddWithValue("@Group", group);
                command.Parameters.AddWithValue("@AlarmType", alarmType);

                try
                {
                    command.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("记录失败：" + ex.Message);
  
                }
            }
        }

   
        public static void StartTimer(string group, int countdownTime, int frequency)
        {
            DateTime startTime = DateTime.Now;

            bool shouldStop = false;

            while (!shouldStop)
            {
                DateTime currentTime = DateTime.Now;
                TimeSpan elapsedTime = currentTime - startTime;

                if (elapsedTime.TotalSeconds >= countdownTime)
                {
                    using (SqlConnection connection = new SqlConnection(connectionString))
                    {
                        connection.Open();

                        bool hasNewData = CheckIfNewDataExists(group, connection);

                        if (hasNewData)
                        {
                             string latestCategory = GetLatestCategory(group, connection);

                            if (latestCategory == "1")
                            {
                                shouldStop = true;
                                RecordToDatabase(group, connection, "Process Alarm");
                                
                            }
                            if (latestCategory == "3")
                            {
                                shouldStop = true;
                                RecordToDatabase(group, connection, "System Alarm");
                            }
                            if (latestCategory == "7")
                            {
                                shouldStop = true;
                                RecordToDatabase(group, connection, "Operator Change");
                            }
                        }
                    }

                    startTime = DateTime.Now; 
                }

                Thread.Sleep(frequency);
            }
        }
    }
}
